package com.yugao.fintech.draper.security.util;

import com.yugao.fintech.draper.core.constant.SecurityConstants;
import com.yugao.fintech.draper.core.exception.BaseException;
import com.yugao.fintech.draper.core.util.WebUtil;
import com.yugao.fintech.draper.security.SecurityUser;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Objects;

/**
 * Security安全工具类
 */
@UtilityClass
public class SecurityUserUtil {

	/**
	 * 获取Authentication
	 */
	public Authentication getAuthentication() {
		return SecurityContextHolder.getContext().getAuthentication();
	}

	/**
	 * 获取当前用户权限
	 * @return 用户权限
	 */
	public Collection<? extends GrantedAuthority> getAuthorities() {
		Authentication authentication = getAuthentication();
		return authentication.getAuthorities();
	}

	/**
	 * 获取用户
	 */
	public SecurityUser getCurrentUser(Authentication authentication) {
		Object principal = authentication.getPrincipal();
		if (principal instanceof SecurityUser) {
			return (SecurityUser) principal;
		}
		return null;
	}

	/**
	 * 获取用户
	 */
	public SecurityUser getCurrentUser() {
		Authentication authentication = getAuthentication();
		SecurityUser userDetail = getCurrentUser(authentication);
		if (userDetail == null) {
			throw new BaseException("获取用户信息失败");
		}
		return userDetail;
	}

	/**
	 * 获取用户名称
	 * @return username
	 */
	public String getUsername() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null) {
			return null;
		}
		return authentication.getName();
	}

	/**
	 * 获取客户端ID
	 * <p>
	 * 兼容两种方式获取OAuth2客户端信息（client_id、client_secret） <br/>
	 * 方式一：client_id、client_secret放在请求路径中 <br/>
	 * 方式二：放在请求头（Request Headers）中的Authorization字段，且经过加密，例如 Basic Y2xpZW50OnNlY3JldA==
	 * 明文等于 client:secret
	 */
	@SneakyThrows
	public String getClientId() {
		HttpServletRequest request = WebUtil.getRequest();
		BasicAuthenticationConverter converter = new BasicAuthenticationConverter();

		return converter.convert(request).getName();
	}

	public String getAuthType() {
		HttpServletRequest request = WebUtil.getRequest();
		// 从请求路径中获取
		return request.getParameter(SecurityConstants.AUTH_TYPE);
	}

	/**
	 * 获取请求中携带的租户id
	 * @return 租户id
	 */
	public static Long getTenantId(HttpServletRequest request) {
		String header = request.getHeader("TENANT-ID");
		String parameter = request.getParameter("TENANT-ID");
		if (Objects.isNull(header) && Objects.isNull(parameter)) {
			return null;
		}
		return Objects.nonNull(header) ? Long.valueOf(header) : Long.valueOf(parameter);
	}

}